package com.ebraga.trackerclub.android.view;

import java.text.DecimalFormat;
import java.util.Date;

import android.content.Context;
import android.location.Location;
import android.location.LocationListener;
import android.location.LocationManager;
import android.os.Bundle;

import com.ebraga.trackerclub.android.R;
import com.ebraga.trackerclub.android.handler.service.PositionServiceHandler;
import com.ebraga.trackerclub.android.util.AndroidApplication;
import com.ebraga.trackerclub.android.util.DLog;
import com.ebraga.trackerclub.android.util.UtilView;
import com.ebraga.trackerclub.android.util.api.AndroidContext;
import com.ebraga.trackerclub.android.util.core.AndroidContextImpl;
import com.ebraga.trackerclub.android.vo.PositionVO;
import com.ebraga.trackerclub.android.vo.UserVO;

public class MyLocationListener implements LocationListener {

	Context applicationContext;
	String addressText;

	public MyLocationListener(Context applicationContext) {
		this.applicationContext = applicationContext;
		
		addressText = null;
		
		startInitialPosition(applicationContext);		
		
	}
	


	private AndroidContext getAndroidContext() {
		AndroidContext context = new AndroidContextImpl();

		context.setContext(applicationContext);
		return context;
	}		
	

	//Inicia com a última posição conhecida.
	private void startInitialPosition(Context applicationContext) {
		
		LocationManager lm = (LocationManager) applicationContext.getSystemService(Context.LOCATION_SERVICE);
		//Recuperar última posição conhecida fornecida pelo GPS
		Location lastKnownLocationGpsProvider = lm.getLastKnownLocation(LocationManager.GPS_PROVIDER);
		
		//Recuperar última posição conhecida fornecida pela REDE
		Location lastKnownLocationNetwordProvider = lm.getLastKnownLocation(LocationManager.NETWORK_PROVIDER);
		
		if (lastKnownLocationGpsProvider != null) {
			getBetterLocation(lastKnownLocationGpsProvider);
		}
		
		if (lastKnownLocationNetwordProvider != null) {
			getBetterLocation(lastKnownLocationNetwordProvider);
		}
		
	}


	double latitudeGlobal = -10.973031;
	double longitudeGlobal = -20.382929;      
	boolean firstPosition = true;
	private final int TEN_SECONDS = 1000 * 10;
	private Location currentBestLocation;
	boolean mapPage = false;  	
	private final int ONE_MINUTE = 1;
	private Date lastAddressText = new Date();
	
	public void onLocationChanged(Location loc) {

		getBetterLocation(loc);

	}

	public void getBetterLocation(Location loc) {
		if (isBetterLocation(loc, currentBestLocation)) {

			currentBestLocation = loc;

			if (loc != null) {
				DecimalFormat dFormat = new DecimalFormat("##.#######");
				String sLatitude = dFormat.format(loc.getLatitude())
						.replace(',', '.');
				String sLongitude = dFormat.format(loc.getLongitude())
						.replace(',', '.');
				latitudeGlobal = Double.valueOf(sLatitude);
				longitudeGlobal = Double.valueOf(sLongitude);
				Float speed = loc.getSpeed();
				firstPosition = false;

				UserVO userVO = UtilView.getUserSession(applicationContext.getApplicationContext());
				
				PositionVO positionVO = new PositionVO();
				if (userVO != null) {
					positionVO.setImei(userVO.getImei());
				}
				
				if (speed > 0) {
					speed = speed * 3600/1000;
				}
				positionVO.setAccuracy(String.valueOf(loc.getAccuracy()));
				positionVO.setSpeed(String.valueOf(speed));
				positionVO.setLatitude(sLatitude);
				positionVO.setLongitude(sLongitude);
				positionVO.setDateLastPosition(new Date(loc.getTime()));
				
				if (LocationManager.NETWORK_PROVIDER.equals(loc.getProvider())) {
					positionVO.setProvider(applicationContext.getString(R.string.provider_network));
				} else {
					positionVO.setProvider(applicationContext.getString(R.string.provider_gps));
				}

				AndroidApplication androidApplication  = (AndroidApplication) applicationContext.getApplicationContext();
				androidApplication.setGpsInfoVO(positionVO);

				PositionServiceHandler positionServiceHandler = new PositionServiceHandler(getAndroidContext());
				try {
					positionServiceHandler.sendPositionData(positionVO);
				} catch (Exception e) {
					DLog.d(e.getMessage());
				}

				//Toast.makeText(getBaseContext(), msg, Toast.LENGTH_LONG).show();


			}

		}
	}

	//Faz algumas validações para ver se a posição é aceitável
	//Exemplo de validação que poder ser utiliada. Accuracy, Data hora da ultima atualização, etc.
	public PositionVO acceptablePosition() {
		PositionVO positionVO = null;
		
		AndroidApplication androidApplication  = (AndroidApplication) applicationContext.getApplicationContext();
		if (androidApplication != null && androidApplication.getGpsInfoVO() != null) {
				positionVO = (PositionVO) androidApplication.getGpsInfoVO();
				
				//TODO Quando a classe ParameterHandler estiver pronta, utilizar o parametro GPS_ACCEPTABLE_ACCURACY para recuperar o valor.
				if (Double.parseDouble(positionVO.getAccuracy()) > 500) {
					//UtilView.sendNotification(androidApplication, "Margem de erro = " + positionVO.getAccuracy());
					return null;
				}
		}
		
		return positionVO;
	}

	/** Checks whether two providers are the same */
	private boolean isSameProvider(String provider1, String provider2) {
		if (provider1 == null) {
			return provider2 == null;
		}
		return provider1.equals(provider2);
	}

	/**
	 * Determines whether one Location reading is better than the current
	 * Location fix
	 * 
	 * @param location
	 *            The new Location that you want to evaluate
	 * @param currentBestLocation
	 *            The current Location fix, to which you want to compare the new
	 *            one
	 */
	protected boolean isBetterLocation(Location location,
			Location currentBestLocation) {
		if (currentBestLocation == null) {
			// A new location is always better than no location
			return true;
		}

		// Check whether the new location fix is newer or older
		long timeDelta = location.getTime() - currentBestLocation.getTime();
		boolean isSignificantlyNewer = timeDelta > TEN_SECONDS;
		boolean isSignificantlyOlder = timeDelta < -TEN_SECONDS;
		boolean isNewer = timeDelta > 0;

		// If it's been more than two minutes since the current location, use
		// the new location
		// because the user has likely moved
		if (isSignificantlyNewer) {
			return true;
			// If the new location is more than two minutes older, it must be
			// worse
		} else if (isSignificantlyOlder) {
			return false;
		}

		// Check whether the new location fix is more or less accurate
		int accuracyDelta = (int) (location.getAccuracy() - currentBestLocation
				.getAccuracy());
		boolean isLessAccurate = accuracyDelta > 0;
		boolean isMoreAccurate = accuracyDelta < 0;
		boolean isSignificantlyLessAccurate = accuracyDelta > 200;

		// Check if the old and new location are from the same provider
		boolean isFromSameProvider = isSameProvider(location.getProvider(),
				currentBestLocation.getProvider());

		// Determine location quality using a combination of timeliness and
		// accuracy
		if (isMoreAccurate) {
			return true;
		} else if (isNewer && !isLessAccurate) {
			return true;
		} else if (isNewer && !isSignificantlyLessAccurate
				&& isFromSameProvider) {
			return true;
		}
		return false;
	}


	@Override
	public void onProviderDisabled(String arg0) {

	}


	@Override
	public void onProviderEnabled(String arg0) {

	}


	@Override
	public void onStatusChanged(String arg0, int arg1, Bundle arg2) {

	}	

}